use std::fmt::{self, Debug};
use serde::de;

#[derive(Debug, Clone)]
pub struct Bytes (Vec<u8>);
impl Bytes {
    #[inline]
    pub fn new(slice: &[u8]) -> Self {
        let mut v = Vec::<u8>::new();
        v.extend_from_slice(slice);
        Self(v)
    }
    #[inline]
    pub fn as_bytes(&self) -> &[u8] {
        self.0.as_slice()
    }
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }
}

impl From<&[u8]> for Bytes {
    fn from(v: &[u8]) -> Self {
        Bytes::new(v)
    }
}
impl From<&str> for Bytes {
    fn from(v: &str) -> Self {
        Bytes::new(v.as_bytes())
    }
}
impl From<String> for Bytes {
    fn from(v: String) -> Self {
        Bytes::new(v.as_bytes())
    }
}

impl<'de> de::Deserialize<'de> for Bytes {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        struct BytesVisitor;
        impl<'de> de::Visitor<'de> for BytesVisitor {
            type Value = Bytes;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("Bytes(Vec<u8>)")
            }
            fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E> 
            where 
                E: de::Error,
            {
                Ok(Bytes::new(v))
            }
            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> 
            where 
                E: de::Error,
            {
                Ok(Bytes::new(v))
            }
        }
        deserializer.deserialize_bytes(BytesVisitor)
    }

}
impl PartialEq for Bytes {
    fn eq(&self, other: &Self) -> bool {
        self.0 == other.0
    }      
}
impl Eq for Bytes {}


#[cfg(test)]
mod test {
    use super::*;
    use crate::from_slice;
    #[test]
    fn bytes_deserialize_test(){
        let origin = &b"00000"[..];
        let expect = Bytes::new(origin);
        assert_eq!(origin, expect.as_bytes());

        let b:Bytes = from_slice(origin).unwrap();
        assert_eq!(b, expect);
    }
}
